<script setup lang="ts">
import { nextTick, ref } from 'vue';

const apiKey = 'sk-5318d9018a434410b7903a815f12f522';
const appId = 'ff97bc0e505c443484dd329d10742e0e'; // 替换为实际的应用 ID
const url = `https://dashscope.aliyuncs.com/api/v1/apps/${appId}/completion`;
const messagesRef = ref(null);
const messages = ref([
  { role: 'assistant', content: '你好！我是AI助手，有什么可以帮您？' },
]);
const isLoading = ref(false);
const inputText = ref('');
const sendMessage = async () => {
  if (!inputText.value.trim()) return;

  // 添加用户消息
  messages.value.push({ role: 'user', content: inputText.value });
  const userInput = inputText.value;
  inputText.value = '';

  try {
    // 添加初始的AI消息
    messages.value.push({ role: 'assistant', content: '' });
    const aiMessageIndex = messages.value.length - 1;

    const response = await fetch(url, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
        'X-DashScope-SSE': 'enable',
      },
      body: JSON.stringify({
        input: { prompt: userInput },
        parameters: {},
        debug: {},
      }),
      // signal: abortController.signal, // 使用 signal 来控制请求
    });

    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const reader = response.body?.getReader();
    const decoder = new TextDecoder('utf-8');
    let accumulatedContent = '';
    let buffer = '';
    let lastLength = 0; // 记录上次 `accumulatedContent` 的长度
    if (reader) {
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          // 输出完毕时可做自定义操作
          console.log('流式数据读取完成');
          break;
        }

        buffer += decoder.decode(value, { stream: true });

        // 处理分割SSE事件，SSE消息通常以两个换行符分隔 "\n\n"
        const sseMessages = buffer.split('\n');
        buffer = sseMessages.pop() || ''; // 保留未解析的部分
        // console.log("Messages:", messages);
        for (const message of sseMessages) {
          // 逐行处理每个事件数据
          if (message.startsWith('data:')) {
            try {
              // 提取 `data:` 后的 JSON 并解析
              const jsonString = message.replace(/^data:\s*/, '');
              const parsedData = JSON.parse(jsonString);
              const newContent = parsedData.output?.text || '';
              // 追加新内容（防止相同内容重复添加）
              // 2️⃣ **防止重复拼接相同的文本**
              // 1️⃣ **基于文本去重**：只添加未出现的内容
              // 1️⃣ **避免重复拼接：只添加新出现的部分**
              if (newContent.startsWith(accumulatedContent)) {
                // 说明 newContent 是对 accumulatedContent 的重复
                accumulatedContent = newContent;
              } else {
                // 只提取 `newContent` 中比 `accumulatedContent` 新的部分
                const addedText = newContent.slice(lastLength);
                accumulatedContent += addedText;
              }
              console.log(accumulatedContent);
              // 更新前端 UI
              messages.value[aiMessageIndex].content = accumulatedContent;
              scrollToBottom();
              // 3️⃣ **更新 lastLength 记录**
              lastLength = accumulatedContent.length;
            } catch (error) {
              console.error('JSON 解析错误:', error);
            }
          }
        }
      }
    }
  } catch (error) {
    // 用于终止流式输出时抛出异常
    if (error.name === 'AbortError') {
      console.log('Fetch aborted:', error);
    } else {
      console.error('Fetch error:', error);
    }
  }
};
// const scrollToBottom = () => {
// 	const container = document.querySelector(".messages");
// 	if (container) {
// 		setTimeout(() => {
// 			container.scrollTop = container.scrollHeight;
// 		}, 50);
// 	}
// };
// 解析json(由于流式输出可能一次输出多个json,此处需要额外处理)
const extractJsonObjects = (str) => {
  const jsonObjects = [];
  let depth = 0;
  let start = 0;
  for (let i = 0; i < str.length; i++) {
    switch (str[i]) {
      case '{': {
        if (depth === 0) start = i;
        depth++;
        break;
      }
      case '}': {
        depth--;
        if (depth === 0) {
          const jsonStr = str.substring(start, i + 1).trim();
          try {
            const parsedJson = JSON.parse(jsonStr);
            jsonObjects.push(parsedJson);
          } catch {
            console.error('Invalid JSON:', jsonStr);
          }
        }
        break;
      }
    }
  }

  return jsonObjects;
};

const scrollToBottom = () => {
  nextTick(() => {
    const messagesContainer = messagesRef.value;
    if (messagesContainer) {
      messagesContainer.scrollTop = messagesContainer.scrollHeight;
    }
  });
};
</script>

<template>
  <div class="chat-container">
    <div class="messages" ref="messagesRef">
      <div
        v-for="(message, index) in messages"
        :key="index"
        :class="message.role"
      >
        <div class="message-bubble">
          <!-- 添加加载动画 -->
          <span v-if="!message.content && index === messages.length - 1">
            <span class="loading-dot">.</span>
            <span class="loading-dot">.</span>
            <span class="loading-dot">.</span>
          </span>
          {{ message.content }}
        </div>
      </div>
    </div>

    <div class="input-area">
      <input
        v-model="inputText"
        @keyup.enter="sendMessage"
        placeholder="输入你的消息..."
      />
      <button @click="sendMessage">发送</button>
    </div>
  </div>
</template>
<style scoped lang="scss">
@keyframes dot-pulse {
  0%,
  100% {
    opacity: 0;
  }

  50% {
    opacity: 1;
  }
}

.chat-container {
  max-width: 600px;
  padding: 20px;
  margin: 2rem auto;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
}

.messages {
  height: 400px;
  padding: 10px;
  margin-bottom: 20px;
  overflow-y: auto;
  background: #f8f9fa;
  border-radius: 4px;
}

.user {
  margin: 10px 0;
  text-align: right;
}

.assistant {
  margin: 10px 0;
  text-align: left;
}

.message-bubble {
  display: inline-block;
  max-width: 80%;
  padding: 8px 12px;
  border-radius: 12px;
}

.user .message-bubble {
  color: white;
  background: #007bff;
}

.assistant .message-bubble {
  color: #212529;
  background: #e9ecef;
}

.input-area {
  display: flex;
  gap: 10px;
}

input {
  flex: 1;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

button {
  padding: 8px 16px;
  color: white;
  cursor: pointer;
  background: #007bff;
  border: none;
  border-radius: 4px;
}

/* 添加加载动画样式 */
.loading-dot {
  opacity: 0;
  animation: dot-pulse 1.4s infinite;
}

.loading-dot:nth-child(1) {
  animation-delay: 0s;
}

.loading-dot:nth-child(2) {
  animation-delay: 0.2s;
}

.loading-dot:nth-child(3) {
  animation-delay: 0.4s;
}
</style>
